﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using SelfService.Helpers;
using SelfService.Model.Interface;
using SelfService.Model.Models;
using SelfService.Model.Request;
using TT;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Mvc;

namespace SelfService.Controllers
{
    [AuthorizeJwtWithCookie]
    public partial class SysPrescriptionController
    {
        private static readonly object Locker = new();

        [ActionDescription("查询缴费清单")]
        [HttpGet("List")]
        public async Task<Result<SysPrescription[]>> List([FromQuery] Guid? patientId)
        {
            try
            {
                //查询患者
                var result = await this.CheckPatient(patientId, "查询缴费清单");
                if (result.Code != 200)
                {
                    return new Result<SysPrescription[]>()
                    {
                        Code = 1,
                        Message = result.Message
                    };
                }
                var patient = result.Data;
                //调用HIS接口
                IHisOrder service;
                try
                {
                    var scope = Wtm.ServiceProvider.CreateScope();
                    service = scope.ServiceProvider.GetRequiredService<IHisOrder>();
                }
                catch (Exception)
                {
                    return new Result<SysPrescription[]>()
                    {
                        Code = 1,
                        Message = "服务端没有启用该业务"
                    };
                }
                var data = await service.GetOrderList(patient);
                if (data.Code == 200)
                {
                    this.Logger($"查询缴费清单, 请求数据:{data.Request}, 返回数据:{data.Response}", ActionLogTypesEnum.Debug);
                    var list = new List<SysPrescription>();
                    foreach (var element in data.Data)
                    {
                        //保存缴费数据到数据库
                        var order = await DC.Set<SysPrescription>().FirstOrDefaultAsync(e =>
                            e.TradeNo == element.TradeNo && 
                            e.Code == element.Code &&
                            e.CardNo == element.CardNo);
                        if (order == null)
                        {
                            order = new SysPrescription();
                            order.CopyPropertyFrom(element);
                            order.ID = Guid.NewGuid();
                            order.PatientId = patient.ID;
                            order.UpdateTime = DateTime.Now;
                            order.Status = SysOrderStatus.未缴费;
                            order.CreateTime ??= DateTime.Now;
                            order.CreateBy ??= Wtm.LoginUserInfo.ITCode;
                            order.UpdateBy = Wtm.LoginUserInfo.ITCode;
                            await DC.Set<SysPrescription>().AddAsync(order);
                        }
                        list.Add(order);
                    }
                    return new Result<SysPrescription[]>()
                    {
                        Data = list.ToArray()
                    };
                }
                else
                {
                    this.Logger($"查询缴费清单, 请求数据:{data.Request}, 返回数据:{data.Response}", ActionLogTypesEnum.Exception);
                    return new Result<SysPrescription[]>
                    {
                        Code = 1,
                        Message = "查询失败"
                    };
                }
            }
            catch (Exception e)
            {
                this.Logger($"查询缴费清单发生异常. 用户:[{patientId}], 异常信息: {JsonConvert.SerializeObject(e)}", ActionLogTypesEnum.Exception);
                return new Result<SysPrescription[]>()
                {
                    Code = 1,
                    Message = "查询失败"
                };
            }
        }
        
        [ActionDescription("缴费")]
        [HttpPost("PayOrder")]
        [ModelFilter]
        public async Task<Result<SysPrescription>> Pay([FromBody] PayOrderRequest request)
        {
            try
            {
                var pay = await DC.Set<SysPay>().Include(e => e.PayType).FirstOrDefaultAsync(e => e.ID == request.PayId);
                if (pay == null)
                {
                    this.Logger($"检测到不存在的PayId, 请检查是否有入侵行为, 请求信息:{JsonConvert.SerializeObject(request)}", ActionLogTypesEnum.Exception);
                    return new Result<SysPrescription>()
                    {
                        Code = 1,
                        Message = "非法请求, 已经被纪录"
                    };
                }
                if (pay.PayStatus != PayStatusEnum.支付成功)
                {
                    this.Logger($"检测到未支付的订单在尝试完成缴费操作, 请求信息:{JsonConvert.SerializeObject(request)}", ActionLogTypesEnum.Exception);
                    return new Result<SysPrescription>()
                    {
                        Code = 1,
                        Message = "非法请求, 已经被纪录"
                    };
                }
                if (pay.UseStatus == UseStatusEnum.成功)
                {
                    this.Logger($"检测已经使用的支付记录在尝试充值, 请求信息:{JsonConvert.SerializeObject(request)}", ActionLogTypesEnum.Exception);
                    return new Result<SysPrescription>()
                    {
                        Code = 1,
                        Message = "非法请求, 已经被纪录"
                    };
                }
                SysPrescription prescription;
                //线程锁, 防止重复提交
                lock (Locker)
                {
                    if (DC.Set<SysPrescription>().Any(e => e.PayId == request.PayId))
                    {
                        this.Logger($"检测到有行为在尝试使用已经用过的支付单据进行缴费, 请求信息:{JsonConvert.SerializeObject(request)}", ActionLogTypesEnum.Exception);
                        return new Result<SysPrescription>()
                        {
                            Code = 1,
                            Message = "非法请求, 已经被纪录"
                        };
                    }
                    prescription = DC.Set<SysPrescription>().FirstOrDefault(e => e.ID == request.OrderId);
                    if (prescription == null)
                    {
                        return new Result<SysPrescription>()
                        {
                            Code = 1,
                            Message = "订单不存在"
                        };
                    }

                    if (prescription.Status == SysOrderStatus.已缴费)
                    {
                        return new Result<SysPrescription>()
                        {
                            Code = 1,
                            Message = "已经缴费完成, 请勿重复缴费."
                        };
                    }

                    if (prescription.Status == SysOrderStatus.缴费中)
                    {
                        return new Result<SysPrescription>()
                        {
                            Code = 1,
                            Message = "正在缴费中, 请勿重复提交."
                        };
                    }

                    if (prescription.Amount != pay.Amount)
                    {
                        this.Logger($"检测到有行为在尝试使用不等于缴费金额的支付单据进行缴费, 请求信息:{JsonConvert.SerializeObject(request)}", ActionLogTypesEnum.Exception);
                        return new Result<SysPrescription>()
                        {
                            Code = 1,
                            Message = "非法请求, 已经被纪录"
                        };
                    }
                    prescription.Status = SysOrderStatus.缴费中;
                    DC.SaveChanges();
                }
                //查询患者
                var result = await this.CheckPatient(prescription.PatientId, "缴费");
                if (result.Code != 200)
                {
                    return new Result<SysPrescription>()
                    {
                        Code = 1,
                        Message = result.Message
                    };
                }
                //调用HIS接口
                IHisOrder service;
                try
                {
                    service = Wtm.ServiceProvider.GetService<IHisOrder>();
                }
                catch (Exception)
                {
                    return new Result<SysPrescription>()
                    {
                        Code = 1,
                        Message = "服务端没有启用该业务"
                    };
                }

                if (service == null)
                {
                    return new Result<SysPrescription>()
                    {
                        Code = 1,
                        Message = "服务端没有启用该业务"
                    };
                }
                var data = await service.Pay(prescription, pay);
                if (data.Code == 200)
                {
                    prescription.Status = SysOrderStatus.已缴费;
                    prescription.PayId = pay.ID;
                    prescription.UpdateTime = DateTime.Now;
                    prescription.UpdateBy = Wtm.LoginUserInfo.ITCode;
                    pay.UseStatus = UseStatusEnum.成功;
                    await DC.SaveChangesAsync();
                    this.Logger($"缴费成功, 请求数据:{data.Request}, 返回数据:{data.Response}", ActionLogTypesEnum.Debug);
                    return new Result<SysPrescription>()
                    {
                        Data = prescription
                    };
                }
                else
                {
                    prescription.Status = SysOrderStatus.缴费失败;
                    prescription.UpdateTime = DateTime.Now;
                    prescription.UpdateBy = Wtm.LoginUserInfo.ITCode;
                    prescription.ErrorMessage = data.Message;
                    await DC.SaveChangesAsync();
                    this.Logger($"缴费失败, 请求数据:{data.Request}, 返回数据:{data.Response}", ActionLogTypesEnum.Exception);
                    return new Result<SysPrescription>()
                    {
                        Code = 1,
                        Message = data.Message.IsNullOrWhiteSpace() ? "缴费失败" : data.Message
                    };
                }
            }
            catch (Exception e)
            {
                this.Logger($"缴费异常. 请求信息:{JsonConvert.SerializeObject(request)}, 异常信息: {JsonConvert.SerializeObject(e)}", ActionLogTypesEnum.Exception);
                return new Result<SysPrescription>()
                {
                    Code = 1,
                    Message = "缴费异常, 请联系工作人员"
                };
            }
        }
        
        [ActionDescription("生成处方")]
        [HttpPost("CreatePrescription")]
        public async Task<Result<SysPrescription>> CreatePrescription([FromBody] CreateTreamentRequest request)
        {
            try
            {
                //查询患者
                var result = await this.CheckPatient(request.PatientId, "查询缴费清单");
                if (result.Code != 200)
                {
                    return new Result<SysPrescription>
                    {
                        Code = 1,
                        Message = result.Message
                    };
                }
                var patient = result.Data;
                var project = await DC.Set<SysMedicalProject>().FirstOrDefaultAsync(e => e.ID == request.ProjectId);
                if (project == null)
                {
                    return new Result<SysPrescription>
                    {
                        Code = 1,
                        Message = "无效的项目ID"
                    };
                }
                if (project.IsDisable)
                {
                    return new Result<SysPrescription>
                    {
                        Code = 1,
                        Message = "该项目已停用"
                    };
                }

                if (project.IsControlQty && request.Qty > 1)
                {
                    return new Result<SysPrescription>
                    {
                        Code = 1,
                        Message = $"【{project.Name}】不允许提交的数量大于1"
                    };
                }

                //调用HIS接口
                IHisOrder service;
                try
                {
                    service = Wtm.ServiceProvider.GetService<IHisOrder>();
                }
                catch (Exception)
                {
                    return new Result<SysPrescription>()
                    {
                        Code = 1,
                        Message = "服务端没有启用该业务"
                    };
                }

                if (service == null)
                {
                    return new Result<SysPrescription>()
                    {
                        Code = 1,
                        Message = "服务端没有启用该业务"
                    };
                }
                var data = await service.CreateOrder(patient, project.Code, request.Qty);
                if (data?.Code == 200)
                {
                    this.Logger($"生成处方成功, 请求数据:{data.Request}, 返回数据:{data.Response}", ActionLogTypesEnum.Debug);
                    var element = data.Data;
                    //保存缴费数据到数据库
                    var order = await DC.Set<SysPrescription>().FirstOrDefaultAsync(e =>
                        e.TradeNo == element.TradeNo &&
                        e.Code == element.Code &&
                        e.CardNo == element.CardNo);
                    if (order == null)
                    {
                        order = new SysPrescription();
                        order.CopyPropertyFrom(element);
                        order.ID = Guid.NewGuid();
                        order.PatientId = patient.ID;
                        order.CreateTime = DateTime.Now;
                        order.UpdateTime = DateTime.Now;
                        order.Status = SysOrderStatus.未缴费;
                        order.CreateBy = Wtm.LoginUserInfo.ITCode;
                        order.UpdateBy = Wtm.LoginUserInfo.ITCode;
                        await DC.Set<SysPrescription>().AddAsync(order);
                        var middle = new SysPrescriptionProjects();
                        middle.ProjectId = project.ID;
                        middle.PrescriptionId = order.ID;
                        middle.ID = Guid.NewGuid();
                        await DC.Set<SysPrescriptionProjects>().AddAsync(middle);
                    }
                    else
                    {
                        order.TradeNo = element.TradeNo;
                    }
                    await DC.SaveChangesAsync();
                    order.Patient = null;
                    this.Logger($"生成处方:{JsonConvert.SerializeObject(order)}");
                    return new Result<SysPrescription>()
                    {
                        Data = order
                    };
                }
                else
                {
                    this.Logger($"生成处方失败, 请求数据:{data?.Request}, 返回数据:{data?.Response}", ActionLogTypesEnum.Exception);
                    return new Result<SysPrescription>
                    {
                        Code = 1,
                        Message = "生成处方失败"
                    };
                }
            }
            catch (Exception e)
            {
                this.Logger($"查询缴费清单发生异常. 用户:[{request.PatientId}], 异常信息: {JsonConvert.SerializeObject(e)}", ActionLogTypesEnum.Exception);
                return new Result<SysPrescription>
                {
                    Code = 1,
                    Message = "生成处方异常"
                };
            }
        }

        [ActionDescription("退款")]
        [HttpGet("Refund")]
        public async Task<Result<object>> Refund([FromQuery] Guid? id)
        {
            try
            {
                if (id.IsNullOrEmpty())
                {
                    return new Result<object>()
                    {
                        Code = 1,
                        Message = "无效的处方ID"
                    };
                }
                SysPrescription prescription;
                lock (Locker)
                {
                    prescription = DC.Set<SysPrescription>().FirstOrDefault(e => e.ID == id);
                    if (prescription == null)
                    {
                        return new Result<object>
                        {
                            Code = 1,
                            Message = "无效的处方ID"
                        };
                    }
                    if (prescription.Status == SysOrderStatus.退款中)
                    {
                        return new Result<object>
                        {
                            Code = 1,
                            Message = "该处方正在退款中, 请勿重复提交"
                        };
                    }
                    if (prescription.Status != SysOrderStatus.已缴费 && prescription.Status != SysOrderStatus.退款失败)
                    {
                        return new Result<object>
                        {
                            Code = 1,
                            Message = "该处方当前状态无法申请退款"
                        };
                    }
                    prescription.Status = SysOrderStatus.退款中;
                    DC.SaveChanges();
                }
                //调用HIS接口
                IHisOrder service;
                try
                {
                    var scope = Wtm.ServiceProvider.CreateScope();
                    service = scope.ServiceProvider.GetRequiredService<IHisOrder>();
                }
                catch (Exception)
                {
                    return new Result<object>
                    {
                        Code = 1,
                        Message = "服务端没有启用该业务"
                    };
                }
                var data = await service.Refund(prescription);
                if (data.Code == 200)
                {
                    prescription.UpdateTime = DateTime.Now;
                    prescription.UpdateBy = Wtm.LoginUserInfo.ITCode;
                    this.Logger($"退款中, 请求数据:{data.Request}, 返回数据:{data.Response}", ActionLogTypesEnum.Job);
                    await DC.SaveChangesAsync();
                    return new Result<object>();
                }
                else
                {
                    prescription.Status = SysOrderStatus.退款失败;
                    prescription.UpdateTime = DateTime.Now;
                    prescription.UpdateBy = Wtm.LoginUserInfo.ITCode;
                    prescription.ErrorMessage = data.Message;
                    await DC.SaveChangesAsync();
                    return new Result<object>
                    {
                        Code = 1,
                        Message = data.Message.IsNullOrWhiteSpace() ? "退款失败" : data.Message
                    };
                }
            }
            catch (Exception e)
            {
                this.Logger($"退款异常. 请求信息:{id}, 异常信息: {JsonConvert.SerializeObject(e)}", ActionLogTypesEnum.Exception);
                return new Result<object>
                {
                    Code = 1,
                    Message = "退款异常, 请联系工作人员"
                };
            }
        }
        

        
    }
}